/*
 * Created on Jun 13, 2005
 */
package clustering.implementations;

import java.io.File;
import java.io.FileInputStream;
import clustering.framework.*;

/**
 * @author Tudor.Ionescu@supelec.fr

NKLDistance

This class is an implementation of the Kullback-Leibler (KL) distance. This distance has to be used with uncompressed files (i.e. in combination with the NULLCompressor class). 

 */
public class NKLDistance implements IDistanceMetric{
	public double Compute(File f_compX, File f_compY, File f_compXY) throws Exception{
		byte [] x_data = new byte[(int)f_compX.length()];
        FileInputStream fis = new FileInputStream(f_compX);
        fis.read(x_data);
        fis.close();
        byte [] y_data = new byte[(int)f_compY.length()];
        fis = new FileInputStream(f_compY);
        fis.read(y_data);
        fis.close();
        double [] P = new double[256];
        double [] Q = new double[256];
        for(int i=0;i<x_data.length;i++){
        	P[Math.abs(x_data[i])]++;
        }
        for(int i=0;i<y_data.length;i++){
        	Q[Math.abs(y_data[i])]++;
        }
        double dkl = 0;
        for(int k=0;k<256;k++){
        	if(P[k]==0)P[k]+=0.000001;
        	if(Q[k]==0)Q[k]+=0.000001;
        	dkl += P[k] * Math.log(P[k]/Q[k]);
        }
        if(dkl < 0)dkl = -dkl;
		return dkl/max(x_data.length,y_data.length);
	}
	double max(int a, int b){
		if(a > b)return (double)a;
		return (double)b;
	}
}
